page.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import { notFound } from "next/navigation";
  2. import { Suspense } from "react";
  3. // import clsx from "clsx";
  4. // import type { ProductReviewList } from "@/types/products/productDetail";
  5. // import { getProductReviews } from "@utils/hooks/getProductReviews";
  6. // import { restApiFetch } from "@utils/bagisto/index";
  7. import {
  8. ProductDetailSkeleton,
  9. RelatedProductSkeleton,
  10. } from "@/components/common/skeleton/ProductSkeleton";
  11. import { BASE_SCHEMA_URL, PRODUCT_TYPE } from "@/utils/constants";
  12. import { GET_PRODUCT_BY_URL_KEY } from "@/graphql";
  13. import {serverGraphqlFetch} from "@utils/bagisto/index";
  14. import {
  15. ProductOption,
  16. SingleProductResponse,
  17. ProductMediaType,
  18. } from "@components/catalog/type";
  19. import { RelatedProductsSection } from "@components/catalog/product/RelatedProductsSection";
  20. import { HeroCarouselShimmer } from "@components/common/slider";
  21. import { ProductMedia } from "@/app/(public)/product/_components/ProductMedia";
  22. import { ProductInformation } from "@/app/(public)/product/_components/ProductInformation";
  23. // import { ProductShortDescription } from "@/app/(public)/product/_components/ProductShortDescription";
  24. import { ProductDetail } from "@/app/(public)/product/_components/ProductDetail";
  25. import ProductDescription from "../_components/ProductDescription";
  26. import SwitchButton from "../_components/SwitchButton";
  27. import ShopServicePanel from "../_components/ShopServicePanel";
  28. import Recommend from "../_components/youmaylike/Recommend"
  29. import { formatFlexibleVariants } from "@/utils/variantTools";
  30. // export const dynamic = 'auto'
  31. // // 'auto' | 'force-dynamic' | 'error' | 'force-static'
  32. export const dynamic = "force-dynamic";
  33. //动态路由中的参数 -- params
  34. export default async function ProductPage({
  35. params,
  36. }: {
  37. params: Promise<{ urlProduct: string[] }>;
  38. searchParams: Promise<{ type: string }>;
  39. }) {
  40. const { urlProduct } = await params;
  41. const fullPath = urlProduct.join("/");
  42. const resProductData = await serverGraphqlFetch<SingleProductResponse,{urlKey: string;}>({
  43. // urlKey, // 产品名称
  44. query: GET_PRODUCT_BY_URL_KEY, // gql查询语句
  45. variables:{
  46. urlKey: fullPath
  47. },
  48. takeAuthorization: false,
  49. });
  50. console.log("productCustomerFeatures----------------------",resProductData);
  51. const product = resProductData.data?.product;
  52. const fetchProductError = resProductData.error;
  53. if (fetchProductError && fetchProductError.extensions.status === 404) return notFound();
  54. if(!product) throw new Error(fetchProductError?.message ?? 'Get product data failed');
  55. // const allReviews: ProductReviewList = await getProductReviews(
  56. // String(product._id),
  57. // );
  58. // 3792
  59. // const res = await restApiFetch({
  60. // api: `/shop/products/${3792}/reviews?page=1&per_page=10&has_images=0&sort=all`,
  61. // method: "GET",
  62. // });
  63. // const allReviews = res?.body?.data;
  64. const questionTotal = 73;
  65. // const imageUrl = getImageUrl(product?.baseImageUrl, baseUrl, NOT_IMAGE);
  66. // JSON-LD数据格式,便于搜索引擎识别页面信息,利于seo
  67. const productJsonLd = {
  68. "@context": BASE_SCHEMA_URL,
  69. "@type": PRODUCT_TYPE,
  70. name: product?.name,
  71. description: product?.description,
  72. sku: product?.sku,
  73. };
  74. const mediaImgs = (product?.images?.edges ?? []).map(
  75. (edge: { node: ProductMediaType }) => {
  76. return edge.node;
  77. },
  78. );
  79. const productOptions: ProductOption[] = product?.productOptions
  80. ? JSON.parse(product?.productOptions)
  81. : [];
  82. const flexibleVariants = formatFlexibleVariants(product?.flexibleVariants);
  83. // const reviews = Array.isArray(product?.reviews?.edges)
  84. // ? product?.reviews.edges.map((e) => e.node)
  85. // : [];
  86. // const VariantImages = isArray(product?.variants?.edges)
  87. // ? product?.variants.edges.map(
  88. // (edge: { node: ProductVariantNode }) => edge.node,
  89. // )
  90. // : [];
  91. return (
  92. <>
  93. <script //SEO
  94. dangerouslySetInnerHTML={{
  95. __html: JSON.stringify(productJsonLd),
  96. }}
  97. type="application/ld+json"
  98. />
  99. <div className="w-full">
  100. <Suspense fallback={<HeroCarouselShimmer />}>
  101. <ProductMedia mediaData={mediaImgs} />
  102. </Suspense>
  103. </div>
  104. <div className="">
  105. <Suspense fallback={<ProductDetailSkeleton />}>
  106. <ProductInformation
  107. key={product._id}
  108. productId={product._id}
  109. name={product?.name || ""}
  110. productOptions={productOptions}
  111. flexibleVariants={flexibleVariants}
  112. isSaleable={product.isSaleable}
  113. shortDescription={product.shortDescription || ""}
  114. />
  115. <ShopServicePanel />
  116. {/* <ProductShortDescription
  117. shortDescription={product.shortDescription || ""}
  118. /> */}
  119. <ProductDescription htmlString={product?.feature || ""} />
  120. <SwitchButton
  121. productId={"3792"} //|| String(product._id)
  122. // reviewList={allReviews}
  123. // reviewTotal={allReviews.length}
  124. questionTotal={questionTotal}
  125. questionList={["aaa"]}
  126. />
  127. <ProductDetail detail={product.description || ""} />
  128. {/* <ProductReviewSection reviews={allReviews} productId={String(product._id)} /> */}
  129. </Suspense>
  130. <Recommend/>
  131. </div>
  132. <Suspense fallback={<RelatedProductSkeleton />}>
  133. <RelatedProductsSection fullPath={fullPath} />
  134. </Suspense>
  135. </>
  136. );
  137. }